package org.luosl.webmagicx.utils

import java.sql.{Connection, DatabaseMetaData, PreparedStatement, ResultSet}

/**
  * Created by luosl on 2017/12/11.
  */
object DbTools {

  def registerDriver(driver:String):Unit = Class.forName(driver)

  /**
    * 执行 execute
    * @param sql sql
    * @param conn 数据库连接
    * @param op 基于 PreparedStatement 的操作
    * @param autoClose 是否自动关闭连接
    * @param params 参数列表
    * @tparam T 泛型
    * @return
    */
  def execute[T](sql:String, conn:Connection, op:PreparedStatement => T ,autoClose: Boolean, params:Any*): T ={
    var ps: PreparedStatement = null
    try{
      ps = conn.prepareStatement(sql)
      // 设置参数
      if(null!=params) {
        params.foldLeft(1){ (idx,param)=> ps.setObject(idx,param); idx+1 }
      }
      op(ps)
    }finally {
      close(ps)
      if(autoClose) close(conn)
    }
  }

  /**
    * 执行查询
    * @param sql sql
    * @param conn conn
    * @param op op
    * @param autoClose autoClose
    * @param params params
    */
  def executeQuery[T](sql:String, conn:Connection, op:ResultSet=>T, autoClose: Boolean, params:Any*): T ={
    val executeOp = (ps:PreparedStatement) => {
      var rs:ResultSet = null
      try {
        rs = ps.executeQuery()
        op(rs)
      }finally close(rs)
    }
    execute(sql, conn, executeOp, autoClose, params:_*)
  }

  /**
    * 执行更新
    * @param sql sql
    * @param conn conn
    * @param autoClose autoClose
    * @param params params
    * @return
    */
  def executeUpdate(sql:String, conn:Connection, autoClose: Boolean, params:Any*):Int = {
    val executeOp: PreparedStatement => Int = (ps: PreparedStatement) => ps.executeUpdate()
    execute(sql, conn, executeOp, autoClose, params:_*)
  }

  /**
    * 判断表是否存在
    * @param tableName 表名称
    * @param conn 数据库连接
    * @param autoClose 是否自动关闭连接
    * @return
    */
  def tableExist(tableName:String, conn:Connection, autoClose: Boolean):Boolean = {
    val meta:DatabaseMetaData = conn.getMetaData
    var rs:ResultSet = null
    try {
      rs = meta.getTables(null, null, tableName, null)
      rs.next()
    }finally {
      close(rs)
      if(autoClose) close(conn)
    }
  }

  /**
    * 关闭
    * @param close close
    */
  def close(close:AutoCloseable):Unit = if(null != close) close.close()

}
